"""剪切板列表组件模块"""

import os
import subprocess
import platform
from pathlib import Path
from typing import Optional
from urllib.parse import unquote
from PySide6.QtWidgets import QListWidget, QListWidgetItem, QLabel, QMenu
from PySide6.QtCore import Qt, Signal
from PySide6.QtGui import QAction

from .database import ClipboardDatabase, ClipboardItem
from .clipboard_item_widget import ClipboardItemWidget


class ClipboardListWidget(QListWidget):
    """剪切板列表组件"""
    
    # 信号定义
    item_selected = Signal(ClipboardItem)  # 项目选中信号
    item_double_clicked = Signal(ClipboardItem)  # 项目双击信号
    selection_cleared = Signal()  # 选择清空信号
    
    def __init__(self, database: ClipboardDatabase, parent=None):
        super().__init__(parent)
        self.database = database
        self.current_offset = 0  # 当前加载的偏移量
        self.page_size = 10  # 每页加载的数量
        self.is_loading = False  # 是否正在加载
        self.has_more_data = True  # 是否还有更多数据
        self.search_text = ""  # 当前搜索文本
        self.setup_ui()
        self.setup_connections()
    
    def setup_ui(self):
        """设置UI"""
        self.setAlternatingRowColors(True)
        self.setSelectionMode(QListWidget.SingleSelection)
        self.setVerticalScrollMode(QListWidget.ScrollPerPixel)
        
        # 启用右键菜单
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.show_context_menu)
        
        # 设置样式
        self.setStyleSheet("""
            QListWidget {
                border: 1px solid #dee2e6;
                border-radius: 6px;
                background-color: #ffffff;
                selection-background-color: grey;
                selection-color: inherit;
                outline: none;
            }
            QListWidget::item {
                padding: 5px;
                border: none;
                background-color: transparent;
                outline: none;
            }
            QListWidget::item:selected {
                background-color: #e3f2fd;
                color: inherit;
                outline: none;
            }
            QListWidget::item:hover {
                background-color: #f3f3f3;
                outline: none;
            }
        """)
    
    def setup_connections(self):
        """设置信号连接"""
        self.itemSelectionChanged.connect(self._on_selection_changed)
        self.itemDoubleClicked.connect(self._on_item_double_clicked)
        # 连接滚动条信号
        self.verticalScrollBar().valueChanged.connect(self._on_scroll_changed)
    
    def load_items(self, limit: int = 20, search_text: str = ""):
        """加载剪切板项目（初始加载）"""
        self.clear()
        self.current_offset = 0
        self.has_more_data = True
        self.search_text = search_text
        
        if search_text:
            items = self.database.search_items(search_text, limit)
        else:
            items = self.database.get_recent_items(limit)
        
        for item in items:
            self.add_item(item)
        
        self.current_offset = len(items)
        
        # 如果加载的数据少于请求的数量，说明没有更多数据了
        if len(items) < limit:
            self.has_more_data = False
    
    def load_more_items(self):
        """加载更多历史数据"""
        if self.is_loading or not self.has_more_data:
            return
        
        self.is_loading = True
        
        # 添加加载提示
        loading_item = self._add_loading_indicator()
        
        # 从数据库加载更多数据
        if self.search_text:
            items = self.database.search_items(self.search_text, self.page_size, self.current_offset)
        else:
            items = self.database.get_recent_items(self.page_size, self.current_offset)
        
        # 移除加载提示
        if loading_item:
            self.takeItem(self.row(loading_item))
        
        # 添加新数据
        for item in items:
            self.add_item(item)
        
        # 更新偏移量
        self.current_offset += len(items)
        
        # 检查是否还有更多数据
        if len(items) < self.page_size:
            self.has_more_data = False
            self._add_no_more_indicator()
        
        self.is_loading = False
    
    def search(self, search_text: str):
        """执行搜索"""
        self.load_items(20, search_text)
    
    def clear_search(self):
        """清除搜索，恢复正常状态"""
        self.search_text = ""
        self.load_items(20, "")
    
    def _add_loading_indicator(self) -> Optional[QListWidgetItem]:
        """添加加载指示器"""
        loading_item = QListWidgetItem()
        loading_label = QLabel("正在加载更多数据...")
        loading_label.setAlignment(Qt.AlignCenter)
        loading_label.setStyleSheet("""
            QLabel {
                color: #666;
                font-style: italic;
                padding: 8px 10px;
                background-color: #f8f9fa;
                border: 1px solid #dee2e6;
                border-radius: 4px;
                margin: 2px;
            }
        """)
        
        # 设置合适的尺寸
        loading_label.setMinimumHeight(40)
        loading_label.adjustSize()
        
        loading_item.setSizeHint(loading_label.sizeHint())
        self.addItem(loading_item)
        self.setItemWidget(loading_item, loading_label)
        
        return loading_item
    
    def _add_no_more_indicator(self):
        """添加没有更多数据的指示器"""
        no_more_item = QListWidgetItem()
        no_more_label = QLabel("没有更多历史数据")
        no_more_label.setAlignment(Qt.AlignCenter)
        no_more_label.setStyleSheet("""
            QLabel {
                color: #999;
                font-style: italic;
                padding: 8px 10px;
                background-color: #f8f9fa;
                border-top: 1px solid #dee2e6;
                border-bottom: 1px solid #dee2e6;
                margin: 2px;
            }
        """)
        
        # 设置合适的尺寸
        no_more_label.setMinimumHeight(40)
        no_more_label.adjustSize()
        
        no_more_item.setSizeHint(no_more_label.sizeHint())
        self.addItem(no_more_item)
        self.setItemWidget(no_more_item, no_more_label)
        
        # 标记为指示器项目，不参与数据操作
        no_more_item.setData(Qt.UserRole, None)
    
    def _on_scroll_changed(self, value):
        """滚动条变化处理"""
        scrollbar = self.verticalScrollBar()
        # 当滚动到底部附近时（距离底部小于50像素）触发加载
        if scrollbar.maximum() - value < 50 and self.has_more_data and not self.is_loading:
            self.load_more_items()
    
    def add_item(self, item: ClipboardItem):
        """添加单个项目到列表"""
        list_item = QListWidgetItem()
        widget = ClipboardItemWidget(item)
        list_item.setSizeHint(widget.sizeHint())
        
        self.addItem(list_item)
        self.setItemWidget(list_item, widget)
        
        # 存储item数据
        list_item.setData(Qt.UserRole, item)
    
    def get_selected_item(self) -> Optional[ClipboardItem]:
        """获取当前选中的项目"""
        current_item = self.currentItem()
        if current_item:
            item_data = current_item.data(Qt.UserRole)
            # 确保不是指示器项目
            if isinstance(item_data, ClipboardItem):
                return item_data
        return None
    
    def refresh(self):
        """刷新列表"""
        self.load_items()
    
    def _on_selection_changed(self):
        """选择变化处理"""
        selected_item = self.get_selected_item()
        if selected_item:
            self.item_selected.emit(selected_item)
        else:
            self.selection_cleared.emit()
    
    def _on_item_double_clicked(self, list_item):
        """双击项目处理"""
        item_data = list_item.data(Qt.UserRole)
        if isinstance(item_data, ClipboardItem):
            self.item_double_clicked.emit(item_data)
    
    def remove_selected_item(self) -> bool:
        """删除选中的项目"""
        selected_item = self.get_selected_item()
        if selected_item:
            # 从数据库删除
            self.database.delete_item(selected_item.id)
            # 从列表中移除
            current_row = self.currentRow()
            if current_row >= 0:
                self.takeItem(current_row)
            # 更新偏移量
            self.current_offset = max(0, self.current_offset - 1)
            return True
        return False
    
    def clear_all_items(self):
        """清空所有项目"""
        # 清空数据库
        self.database.clear_old_items(0)
        # 清空列表
        self.clear()
        # 重置状态
        self.current_offset = 0
        self.has_more_data = True
    
    def get_item_count(self) -> int:
        """获取项目数量（不包括指示器）"""
        count = 0
        for i in range(self.count()):
            item = self.item(i)
            if isinstance(item.data(Qt.UserRole), ClipboardItem):
                count += 1
        return count
    
    def show_context_menu(self, position):
        """显示右键菜单"""
        item = self.itemAt(position)
        if not item:
            return
        
        clipboard_item = item.data(Qt.UserRole)
        if not isinstance(clipboard_item, ClipboardItem):
            return
        
        menu = QMenu(self)
        
        # 复制到剪切板
        copy_action = QAction("📋 复制到剪切板", self)
        copy_action.triggered.connect(lambda: self.copy_item_to_clipboard(clipboard_item))
        menu.addAction(copy_action)
        
        # 如果是文件路径，添加打开目录选项
        if clipboard_item.content_type == "files" or self.is_file_path(clipboard_item.content):
            open_dir_action = QAction("📂 打开所在目录", self)
            open_dir_action.triggered.connect(lambda: self.open_file_directory(clipboard_item.content))
            menu.addAction(open_dir_action)
        
        menu.addSeparator()
        
        # 删除项目
        delete_action = QAction("🗑️ 删除", self)
        delete_action.triggered.connect(lambda: self.delete_item(clipboard_item))
        menu.addAction(delete_action)
        
        # 显示菜单
        menu.exec(self.mapToGlobal(position))
    
    def is_file_path(self, content: str) -> bool:
        """判断内容是否为文件路径"""
        if not content:
            return False
        
        # 检查是否为单行路径
        lines = content.strip().split('\n')
        if len(lines) > 1:
            # 多行时，检查每一行是否都是路径
            return all(self._is_single_path(line.strip()) for line in lines if line.strip())
        else:
            return self._is_single_path(content.strip())
    
    def _is_single_path(self, path: str) -> bool:
        """判断单个字符串是否为文件路径"""
        try:
            original_path = path
            
            # 处理file://格式的URL路径
            if path.startswith('file://'):
                path = unquote(path[7:])  # 移除'file://'前缀并解码
                # Windows路径处理：移除多余的斜杠
                if platform.system() == "Windows" and path.startswith('/'):
                    path = path[1:]  # 移除开头的斜杠
            
            # 使用pathlib检查路径格式
            p = Path(path)
            # 检查是否存在或者是合法的路径格式
            is_path = p.exists() or (len(str(p.parent)) > 1 and ('\\' in path or '/' in path))
            
            # 如果原始路径是file://格式，也认为是路径
            if original_path.startswith('file://'):
                is_path = True
                
            return is_path
        except:
            return False
    
    def copy_item_to_clipboard(self, clipboard_item: ClipboardItem):
        """复制项目到剪切板"""
        try:
            from PySide6.QtWidgets import QApplication
            clipboard = QApplication.clipboard()
            
            if clipboard_item.content_type == "image":
                # 处理图片
                from PySide6.QtGui import QPixmap
                import base64
                try:
                    image_data = base64.b64decode(clipboard_item.content)
                    pixmap = QPixmap()
                    pixmap.loadFromData(image_data)
                    if not pixmap.isNull():
                        clipboard.setPixmap(pixmap)
                except Exception as e:
                    print(f"复制图片失败: {e}")
                    clipboard.setText(clipboard_item.content)
            else:
                # 处理文本和文件路径
                clipboard.setText(clipboard_item.content)
            
            print(f"已复制到剪切板: {clipboard_item.content_type}")
        except Exception as e:
            print(f"复制到剪切板失败: {e}")
    
    def open_file_directory(self, content: str):
        """打开文件所在目录"""
        try:
            lines = content.strip().split('\n')
            # 处理第一个路径
            first_path = lines[0].strip()
            
            # 处理file://格式的URL路径
            if first_path.startswith('file://'):
                # 移除file://前缀并解码URL编码
                first_path = unquote(first_path[7:])  # 移除'file://'前缀
                # Windows路径处理：移除多余的斜杠
                if platform.system() == "Windows" and first_path.startswith('/'):
                    first_path = first_path[1:]  # 移除开头的斜杠
            
            path_obj = Path(first_path)
            
            # 如果是文件，获取其父目录；如果是目录，直接使用
            if path_obj.is_file():
                directory = path_obj.parent
            elif path_obj.is_dir():
                directory = path_obj
            else:
                # 如果路径不存在，尝试获取父目录
                directory = path_obj.parent
                if not directory.exists():
                    print(f"路径不存在: {first_path}")
                    return
            
            # 根据操作系统打开文件管理器
            system = platform.system()
            if system == "Windows":
                # Windows: 使用explorer
                if path_obj.is_file() and path_obj.exists():
                    # 选中文件
                    os.startfile(str(directory))
                else:
                    # 打开目录
                    os.startfile(str(directory))
            elif system == "Darwin":  # macOS
                if path_obj.is_file() and path_obj.exists():
                    # 选中文件
                    subprocess.run(['open', '-R', str(path_obj)], check=True)
                else:
                    # 打开目录
                    subprocess.run(['open', str(directory)], check=True)
            else:  # Linux
                # 尝试使用常见的文件管理器
                try:
                    subprocess.run(['xdg-open', str(directory)], check=True)
                except:
                    try:
                        subprocess.run(['nautilus', str(directory)], check=True)
                    except:
                        try:
                            subprocess.run(['dolphin', str(directory)], check=True)
                        except:
                            print(f"无法打开目录: {directory}")
            
            print(f"已打开目录: {directory}")
        except Exception as e:
            print(f"打开目录失败: {e}")
    
    def delete_item(self, clipboard_item: ClipboardItem):
        """删除指定项目"""
        try:
            # 从数据库删除
            self.database.delete_item(clipboard_item.id)
            
            # 从列表中找到并移除对应项目
            for i in range(self.count()):
                item = self.item(i)
                if item and isinstance(item.data(Qt.UserRole), ClipboardItem):
                    if item.data(Qt.UserRole).id == clipboard_item.id:
                        self.takeItem(i)
                        break
            
            # 更新偏移量
            self.current_offset = max(0, self.current_offset - 1)
            print(f"已删除项目: {clipboard_item.id}")
        except Exception as e:
            print(f"删除项目失败: {e}") 